package defi2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import Utils.Compteur;
import Utils.Utils;
import donnees.Variables;

public class VigenereCoincidence {
	private String messageCrypt;
	private String messageQueAlphabet;
	private String messageCoupe;
	private Map<Integer, String> mapChaine;
	private Map<Character, Compteur> mapCompteur;
	private Map<Integer, Double> mapIndice;
	private List<Double> listeMoyenne;

	public VigenereCoincidence(String message) {
//		Fichier fichier = new Fichier(
//				new File(
//						"C:/Users/Guillaume/Google Drive/ProjetSecurite/Groupe1/Defi2/test.txt"));
		this.messageCrypt = message; //fichier.getContenu(); 
		this.mapChaine = new HashMap<Integer, String>();
		this.mapCompteur = new HashMap<Character, Compteur>();
		this.mapIndice = new HashMap<Integer, Double>();
		this.listeMoyenne = new ArrayList<Double>();
	}
	
	public int trouverCle(){
		//String chaine = "";
		for(int i = 1; i<20; i++){
			decompositionEnChaine(i);
			decompositionEnCaractere();
			calculSurIndice(mapIndice);
			//chaine += i + " : " + affichageIndice() + " \n";
		}
		//System.out.println(chaine);
		return trouverIndice();
	}
	
	public int trouverIndice(){
		int indice = 0;
		for(int i = 0; i<listeMoyenne.size(); i++){
			if( listeMoyenne.get(i) < listeMoyenne.get(indice) ){
				indice = i;
			}
		}
		return indice + 1;
	}
	
	public void calculSurIndice(Map<Integer, Double> map){
		double tmp  = 0.0;
		Set<?> cles = map.keySet();
		Iterator<?> iter = cles.iterator();
		//Parcours la map des chaines decomposees
		while (iter.hasNext()) {
			Integer numero = (Integer) iter.next();
			double soustraction = Math.abs(Variables.indiceEN - map.get(numero));
			tmp += soustraction;
		}
		double moyenne = tmp / map.size();
		listeMoyenne.add(moyenne);
	}
	
	public void decompositionEnChaine(int taille){
		this.messageQueAlphabet = Utils.nettoyerStringMaj(messageCrypt);
		//Boucle pour la taille
		for(int i = 0; i < taille; i++){
			String tmp = "";
			int j = i;
			//Boucle qui parcours la chaine en prennant les caracteres selon la taille
			while( j < messageQueAlphabet.length() ){
				tmp += messageQueAlphabet.charAt(j);
				j = j + taille;
			}
			//Ajout de la chaine decompose
			mapChaine.put(i+1, tmp);
		}
	}
	
	public void decompositionEnCaractere(){
		this.messageCoupe = "";
		Set<?> cles = mapChaine.keySet();
		Iterator<?> iter = cles.iterator();
		//Parcours la map des chaines decomposees
		while (iter.hasNext()) {
			Integer numero = (Integer) iter.next();
			messageCoupe = mapChaine.get(numero);
			//Parcours la chaine decompose
			for( int j = 0; j < messageCoupe.length(); j++){
				char c = messageCoupe.charAt(j);
				if( mapCompteur.containsKey(c) ){
					mapCompteur.get(c).incrementer();
				}
				else{
					Compteur comp = new Compteur();
					comp.setI(1);
					mapCompteur.put(c, comp);
				}
			}
			//System.out.println(affichageCaractere());
			double indice = decompositionEnIndice(mapCompteur);
			mapIndice.put(numero, indice);
			mapCompteur.clear();
		}
		//return mapCompteur;
	}
	
	public double decompositionEnIndice(Map<Character, Compteur> map){
		double nbCara = 0.0;
		double longeurChaine = messageCoupe.length();
		Set<?> cles = map.keySet();
		Iterator<?> iter = cles.iterator();
		//Parcours la map des caractere
		while (iter.hasNext()) {
			Character c = (Character) iter.next();
			//System.out.println(map.get(c).getI() * (map.get(c).getI() - 1));
			nbCara += map.get(c).getI() * (map.get(c).getI() - 1);
		}
		double division = 1 / ( longeurChaine * (longeurChaine - 1));
		double indice = division * nbCara;
		return indice;
	}

	public String affichageIndice() {
		String msg = "";
		Set cles = mapIndice.keySet();
		Iterator iter = cles.iterator();
		while (iter.hasNext()) {
			Integer i = (Integer) iter.next();
			msg += mapIndice.get(i) + " | ";
		}
		return msg;
	}
	
	public String affichageCaractere(){
		String msg = "";
		Set cles = mapCompteur.keySet();
		Iterator iter = cles.iterator();
		while (iter.hasNext()) {
			Character c = (Character) iter.next();
			msg += c + " : " + mapCompteur.get(c).getI() + " \n ";
		}
		return msg;
	}
	
	public String affichageChaine(){
		String msg = "";
		Set cles = mapChaine.keySet();
		Iterator iter = cles.iterator();
		while (iter.hasNext()) {
			Integer i = (Integer) iter.next();
			msg += i + " : " + mapChaine.get(i) + " \n ";
		}
		return msg;
	}

	public static void main(String[] args) {
		VigenereCoincidence v = new VigenereCoincidence("PERTQUDCDJXESCWMPNLVMIQDIZTQFVXAKLRPICCPQSHZYDNCPWEAJWSZGCLMQNRDEOHCGEZTQZYHELEWAUQFROICWHQMYRRUFGBYQSEPVNEQCSEEQWEEAGDSZDCWEOHYDWQERLMFTCCQUNCPPQSKPYFEQOIOHGPREERWIEFSDMXSYGEUELEHUSNLVGPMFVEIVXSUSJPWHIEYSNLCDWMCRTZMICYXMNMFZQASLZQCJPYDSTTKZEPZRECMYWOICYGUESIUGIRCEUTYTIZTJPWHIEYIETYYHUSOFIXESCWHOGDMZSNLVQSQPYJSCAVQSQLMQNRLPQSRLMXLCCGAMKPGQLYLYDAGEHGERCIRAGEIZNMGIYBPP");
		System.out.println(v.trouverCle());
	}
}
